package com.sinosoft.dsp.platform.components.portal.input.picklist;

import java.util.ArrayList;
import java.util.List;

import javax.faces.model.ListDataModel;

import org.primefaces.model.SelectableDataModel;

/**
 * Sino左右选择框模型
 * 
 * @author 潘巍（PeterPan）
 * @since 2011-8-12 上午05:42:40
 * 
 * @param <T>
 */
public class SinoPickListModel<T extends ISinoSelectableDataModel> {
	public static final String ACTION_TYPE_ADD_ALL = "addAll";

	public static final String ACTION_TYPE_ADD = "add";

	public static final String ACTION_TYPE_REMOVE = "remove";

	public static final String ACTION_TYPE_REMOVE_ALL = "removeAll";

	private SinoPickListDataModel source = new SinoPickListDataModel();

	private SinoPickListDataModel target = new SinoPickListDataModel();

	private T[] selectedSources;

	private T[] selectedTargets;

	@SuppressWarnings("unchecked")
	public void action(String type) {
		if (ACTION_TYPE_ADD_ALL.equals(type)) {
			target.addAll((List<T>) source.getWrappedData());
			source.removeAll();
			if (selectedSources != null && selectedSources.length > 0) {
				selectedTargets = selectedSources;
				selectedSources = null;
			}
		} else if (ACTION_TYPE_ADD.equals(type)) {
			if (selectedSources != null) {
				for (T t : selectedSources) {
					target.add(t);
					source.remove(t);
				}
			}
			selectedTargets = selectedSources;
			selectedSources = null;
		} else if (ACTION_TYPE_REMOVE.equals(type)) {
			if (selectedTargets != null) {
				for (T t : selectedTargets) {
					source.add(t);
					target.remove(t);
				}
			}
			selectedSources = selectedTargets;
			selectedTargets = null;
		} else if (ACTION_TYPE_REMOVE_ALL.equals(type)) {
			source.addAll((List<T>) target.getWrappedData());
			target.removeAll();
			if (selectedTargets != null && selectedTargets.length > 0) {
				selectedSources = selectedTargets;
				selectedTargets = null;
			}
		}
	}

	public SinoPickListDataModel getSource() {
		return source;
	}

	public void setSource(SinoPickListDataModel source) {
		this.source = source;
	}

	public T[] getSelectedSources() {
		return selectedSources;
	}

	public void setSelectedSources(T[] selectedSources) {
		this.selectedSources = selectedSources;
	}

	public T[] getSelectedTargets() {
		return selectedTargets;
	}

	public void setSelectedTargets(T[] selectedTargets) {
		this.selectedTargets = selectedTargets;
	}

	public SinoPickListDataModel getTarget() {
		return target;
	}

	public void setTarget(SinoPickListDataModel target) {
		this.target = target;
	}

	public class SinoPickListDataModel extends ListDataModel<T> implements
			SelectableDataModel<T> {

		public SinoPickListDataModel() {
		}

		public SinoPickListDataModel(List<T> ts) {
			super(ts);
		}

		@SuppressWarnings("unchecked")
		public void add(T t) {
			if (this.getWrappedData() == null) {
				this.setWrappedData(new ArrayList<T>());
			}
			((List) this.getWrappedData()).add(t);
			if (this.getRowIndex() == -1) {
				this.setRowIndex(0);
			}
		}

		@SuppressWarnings("unchecked")
		public boolean remove(T t) {
			boolean b = false;
			if (this.getWrappedData() != null) {
				b = ((List) this.getWrappedData()).remove(t);
				if (b) {
					if (this.getRowCount() < 1) {
						this.setRowIndex(-1);
					} else {
						this.setRowIndex(0);
					}
				}
			}
			return b;
		}

		@SuppressWarnings("unchecked")
		public void addAll(List<T> ts) {
			if (this.getWrappedData() == null) {
				this.setWrappedData(new ArrayList<T>());
			}
			((List) this.getWrappedData()).addAll(ts);
			if (this.getRowIndex() == -1) {
				this.setRowIndex(0);
			}
		}

		@SuppressWarnings("unchecked")
		public void removeAll() {
			if (this.getWrappedData() != null) {
				((List) this.getWrappedData()).clear();
				this.setRowIndex(-1);
			}
		}

		@SuppressWarnings("unchecked")
		@Override
		public T getRowData(String rowKey) {
			List<T> ts = (List<T>) getWrappedData();
			if (ts != null)
				for (T t : ts) {
					if (t.getRowKey().equals(rowKey))
						return t;
				}
			return null;
		}

		@Override
		public Object getRowKey(T t) {
			return t.getRowKey();
		}

	}

}
